package com.tegistuff.webos;

import com.intellij.ide.plugins.cl.PluginClassLoader;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * AppComponent.java
 *
 * Copyright (C) 2012 Timo Tegtmeier.
 * Copyright (C) 2011 Janni Kovacs.
 * All rights reserved.
 */
public class AppComponent implements ApplicationComponent {

	public static final Icon ICON = new ImageIcon(AppComponent.class.getResource("icons/webos.png"));
	public static final Icon ADD_ICON = new ImageIcon(AppComponent.class.getResource("icons/new_app.png"));
	public static final Icon NATURE_ICON = new ImageIcon(AppComponent.class.getResource("icons/webos_nature.png"));
	
	public static final String PLUGIN_ID = "com.tegistuff.webos";
    public static final String COMPONENT_NAME = "webOS app development plugin main component";

    public AppComponent() {
    }

    @Override
    public void initComponent() {
        ClassLoader classLoader = this.getClass().getClassLoader();
        if(classLoader instanceof PluginClassLoader) {
            try {
                PluginClassLoader pluginClassLoader = (PluginClassLoader)classLoader;
                File webOSToolsJarFile = new File(AppComponent.getWebOSToolsJarPath());
                URL webOSToolsJarURL = webOSToolsJarFile.toURI().toURL();
                pluginClassLoader.addURL(webOSToolsJarURL);
            } catch (MalformedURLException e) {
            }
        }
        IsSDKSupported();
    }

    @Override
    public void disposeComponent() {
    }

    @NotNull
    @Override
    public String getComponentName() {
        return COMPONENT_NAME;
    }

	public static List<VirtualFile> getWebOSAppFoldersInProject(Project project) {
		return collectDirsInProject(project, new IsAppDir());
	}
    
    public static List<VirtualFile> getWebOSPackageFoldersInProject(Project project) {
        return collectDirsInProject(project, new IsPackageDir());
    }

    public static List<VirtualFile> getWebOSServiceFoldersInProject(Project project) {
        return collectDirsInProject(project, new IsServiceDir());
    }

    public static List<VirtualFile> getWebOSAccountsFoldersInProject(Project project) {
        return collectDirsInProject(project, new IsAccountsDir());
    }

    private static List<VirtualFile> collectDirsInProject(Project project, CheckDirectory checker) {
        ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
        VirtualFile baseDir = project.getBaseDir();
        if (baseDir != null) {
            if (checker.checkDir(baseDir))
                files.add(baseDir);
            VirtualFile[] children = baseDir.getChildren();
            for (VirtualFile child : children) {
                if (child.isDirectory()) {
                    if (checker.checkDir(child)) {
                        files.add(child);
                    }
                }
            }
        }
        return files;
    }

	public static VirtualFile getAppDirForFile(VirtualFile file) {
		while (file != null) {
			if (AppComponent.isWebOSAppDir(file)) {
				return file;
			}
			file = file.getParent();
		}
		return null;
	}
	
	public static boolean isWebOSAppDir(PsiDirectory dir) {
		return isWebOSAppDir(dir.getVirtualFile());
	}

	public static boolean isWebOSAppDir(VirtualFile file) {
		if(!file.isDirectory())
			return false;
		boolean hasAppInfo = file.findChild("appinfo.json") != null;
		boolean parentIsResources = false;
		VirtualFile parent = file.getParent();
		if(parent != null)
			parentIsResources = parent.getName().equals("resources");
		return hasAppInfo && !parentIsResources;
	}

    public static boolean isWebOSPackageDir(VirtualFile file) {
        return file.isDirectory() && (file.findChild("packageinfo.json") != null);
    }

    public static boolean isWebOSServiceDir(VirtualFile file) {
        return file.isDirectory() && (file.findChild("services.json") != null);
    }

    public static boolean isWebOSAccountsDir(VirtualFile file) {
        return file.isDirectory() && (file.findChild("account-templates.json") != null);
    }

	public static String getPalmSDKPath() {
		if(SystemInfo.isWindows)
			return System.getenv("PalmSDK");
		else// if(SystemInfo.isMac || SystemInfo.isLinux)
			return "/opt/PalmSDK/Current";
	}

	public static String getWebOSToolsJarPath() {
		return getPalmSDKPath()+"/share/jars/webos-tools.jar";
	}

    private abstract static class CheckDirectory {
        public abstract boolean checkDir(VirtualFile dir);
    }

    private static class IsAppDir extends CheckDirectory {
        @Override
        public boolean checkDir(VirtualFile dir) {
            return AppComponent.isWebOSAppDir(dir);
        }
    }

    private static class IsPackageDir extends CheckDirectory {
        @Override
        public boolean checkDir(VirtualFile dir) {
            return AppComponent.isWebOSPackageDir(dir);
        }
    }

    private static class IsServiceDir extends CheckDirectory {
        @Override
        public boolean checkDir(VirtualFile dir) {
            return AppComponent.isWebOSServiceDir(dir);
        }
    }

    private static class IsAccountsDir extends CheckDirectory {
        @Override
        public boolean checkDir(VirtualFile dir) {
            return AppComponent.isWebOSAccountsDir(dir);
        }
    }

    public static boolean IsSDKSupported() {
        if(getSDKVersion() < 2) {
            ApplicationManager.getApplication().invokeLater(new Runnable() {
                @Override
                public void run() {
                    Messages.showErrorDialog("Could not find a HP webOS SDK v2.1 or later.\n" +
                            "Please make sure you have the SDK installed properly.\n\n" +
                            "The webOS plugin is unable to work properly without having the SDK installed.",
                            "HP webOS SDK not found");
                }
            });
            return false;
        }
        return true;
    }

    /**
     * Returns 1 or 2 for 1.x and 2.x versions respectively
     *
     * @return 1 or 2
     */
    private static int getSDKVersion() {
        try {
            Class.forName("com.palm.webos.sdk.SDK");
            return 2;
        } catch (ClassNotFoundException e) {
            return 1;
        }
    }
}
